package com.eliza.base.views.learn.graphics

import android.graphics.PointF
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsPressedAsState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Matrix
import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.asComposePath
import androidx.compose.ui.graphics.drawscope.scale
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.core.graphics.plus
import androidx.core.graphics.times
import androidx.graphics.shapes.CornerRounding
import androidx.graphics.shapes.Morph
import androidx.graphics.shapes.RoundedPolygon
import androidx.graphics.shapes.star
import androidx.graphics.shapes.toPath
import com.eliza.base.R
import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.max
import kotlin.math.sin

object ShapesX {

    @Composable
    fun Show() {
        var swi by remember {
            mutableIntStateOf(0)
        }
        Column {
            Button(onClick = { swi = (swi + 1) % 7 }) {
                Text(text = "ShapesX ${swi}")
            }
            when (swi) {
                0 -> Make()
                1 -> MakeRadius()
                2 -> MorphX()
                3 -> AnimaX()
                4 -> clipX()
                5 -> clipXX()
                6 -> ShapesAnimationX.Show()
            }
        }
    }

    @Composable
    private fun Make() {
        Box(
            modifier = Modifier
                .drawWithCache {
                    val roundedPolygon = RoundedPolygon(
                        numVertices = 6,
                        radius = size.minDimension / 2,
                        centerX = size.width / 2,
                        centerY = size.height / 2
                    )
                    /*RoundedPolygon，其中包含表示所请求形状的几何图形。
                    如需在 Compose 应用中绘制该形状，您必须从中获取 Path 对象，以将形状转换为 Compose 知道如何绘制的形式。*/
                    val roundedPolygonPath = roundedPolygon
                        .toPath()
                        .asComposePath()
                    onDrawBehind {
                        drawPath(roundedPolygonPath, color = Color.Blue)
                    }
                }
                .fillMaxSize()
        )
    }

    @Composable
    private fun MakeRadius() {
        Text(text = "Radius(")
        Box(
            modifier = Modifier
                .drawWithCache {
                    val roundedPolygon = RoundedPolygon(
                        numVertices = 3,
                        radius = size.minDimension / 2,
                        centerX = size.width / 2,
                        centerY = size.height / 2,
                        rounding = CornerRounding(
                            size.minDimension / 10f,
                            smoothing = 0.1f
                        )
                    )
                    val roundedPolygonPath = roundedPolygon
                        .toPath()
                        .asComposePath()
                    onDrawBehind {
                        drawPath(roundedPolygonPath, color = Color.Black)
                    }
                }
                .size(100.dp)
        )

    }

    //Morph 对象是一种新形状，表示两个多边形形状之间的动画
    /*如需在两种形状之间变形，请创建两个 RoundedPolygons 和一个采用这两种形状的 Morph 对象。
    如需计算起始形状和结束形状之间的形状，
    请提供介于 0 到 1 之间的 progress 值，以确定起始形状 (0) 和结束形状 (1) 之间的形状：*/
    @Composable
    private fun MorphX() {
        Text(text = "MorphX")
        Box(
            modifier = Modifier
                .drawWithCache {
                    val triangle = RoundedPolygon(
                        numVertices = 3,
                        radius = size.minDimension / 2f,
                        centerX = size.width / 2f,
                        centerY = size.height / 2f,
                        rounding = CornerRounding(
                            size.minDimension / 10f,
                            smoothing = 0.1f
                        )
                    )
                    val square = RoundedPolygon(
                        numVertices = 4,
                        radius = size.minDimension / 2f,
                        centerX = size.width / 2f,
                        centerY = size.height / 2f
                    )

                    val morph = Morph(start = triangle, end = square)
                    val morphPath = morph
                        .toPath(progress = 0.5f)
                        .asComposePath()

                    onDrawBehind {
                        drawPath(morphPath, color = Color.Black)
                    }
                }
                .fillMaxSize()
        )
    }

    @Composable
    private fun AnimaX() {
        val infiniteAnimation = rememberInfiniteTransition(label = "infinite animation")
        val morphProgress = infiniteAnimation.animateFloat(
            initialValue = 0f,
            targetValue = 1f,
            animationSpec = infiniteRepeatable(
                tween(500),
                repeatMode = RepeatMode.Reverse
            ),
            label = "morph"
        )
        Box(
            modifier = Modifier
                .drawWithCache {
                    val triangle = RoundedPolygon(
                        numVertices = 3,
                        radius = size.minDimension / 2f,
                        centerX = size.width / 2f,
                        centerY = size.height / 2f,
                        rounding = CornerRounding(
                            size.minDimension / 10f,
                            smoothing = 0.1f
                        )
                    )
                    val square = RoundedPolygon(
                        numVertices = 4,
                        radius = size.minDimension / 2f,
                        centerX = size.width / 2f,
                        centerY = size.height / 2f
                    )

                    val morph = Morph(start = triangle, end = square)
                    val morphPath = morph
                        .toPath(progress = morphProgress.value)
                        .asComposePath()

                    onDrawBehind {
                        drawPath(morphPath, color = Color.Black)
                    }
                }
                .fillMaxSize()
        )
    }
//

    private fun RoundedPolygon.getBounds() =
        calculateBounds().let { Rect(it[0], it[1], it[2], it[3]) }

    class RoundedPolygonShape(
        private val polygon: RoundedPolygon,
        private var matrix: Matrix = Matrix()
    ) : Shape {
        private var path = Path()

        override fun createOutline(
            size: Size,
            layoutDirection: LayoutDirection,
            density: Density
        ): Outline {
            path.rewind()
            path = polygon.toPath().asComposePath()
            matrix.reset()
            val bounds = polygon.getBounds()
            val maxDimension = max(bounds.width, bounds.height)
            matrix.scale(size.width / maxDimension, size.height / maxDimension)
            matrix.translate(-bounds.left, -bounds.top)

            path.transform(matrix)
            return Outline.Generic(path)
        }
    }

    @Composable
    private fun clipX() {

        val hexagon = remember {
            RoundedPolygon(
                6,
                rounding = CornerRounding(0.2f)
            )
        }
        val clip = remember(hexagon) {
            RoundedPolygonShape(polygon = hexagon)
        }
        Box(
            modifier = Modifier
                .clip(clip)
                .background(MaterialTheme.colorScheme.secondary)
                .size(200.dp)
        ) {
            Text(
                "Hello Compose",
                color = MaterialTheme.colorScheme.onSecondary,
                modifier = Modifier.align(Alignment.Center)
            )
        }

    }

    @Composable
    private fun clipXX() {
        val hexagon = remember {
            RoundedPolygon(
                6,
                rounding = CornerRounding(0.2f)
            )
        }
        val clip = remember(hexagon) {
            RoundedPolygonShape(polygon = hexagon)
        }
        Box(
            modifier = Modifier.fillMaxSize(),
            contentAlignment = Alignment.Center
        ) {
            Image(
                painter = painterResource(id = R.drawable.ic_launcher),
                contentDescription = "Dog",
                contentScale = ContentScale.Crop,
                modifier = Modifier
                    .graphicsLayer {
                        this.shadowElevation = 6.dp.toPx()
                        this.shape = clip
                        this.clip = true
                        this.ambientShadowColor = Color.Black
                        this.spotShadowColor = Color.Black
                    }
                    .size(200.dp)

            )
        }

    }

}
//failed to open device: Access denied (insufficient permissions)
object ShapesAnimationX {
    @Composable
    fun Show() {
        var swi by remember {
            mutableIntStateOf(0)
        }
        Column {
            Button(onClick = { swi = (swi + 1) % 3 }) {
                Text(text = "ShapesAnimationX ${swi}")
            }
            when (swi) {
                0 -> ClickToShape()
                1 -> RotatingScallopedProfilePic()
                2 -> HeartShape()
            }
        }
    }


    //点击时变形按钮
    class MorphPolygonShape(
        private val morph: Morph,
        private val percentage: Float
    ) : Shape {

        private val matrix = Matrix()
        override fun createOutline(
            size: Size,
            layoutDirection: LayoutDirection,
            density: Density
        ): Outline {
            // Below assumes that you haven't changed the default radius of 1f, nor the centerX and centerY of 0f
            // By default this stretches the path to the size of the container, if you don't want stretching, use the same size.width for both x and y.
            matrix.scale(size.width / 2f, size.height / 2f)
            matrix.translate(1f, 1f)

            val path = morph.toPath(progress = percentage).asComposePath()
            path.transform(matrix)
            return Outline.Generic(path)
        }
    }

    @Composable
    fun ClickToShape(modifier: Modifier = Modifier) {
        val shapeA = remember {
            RoundedPolygon(
                6,
                rounding = CornerRounding(0.2f)
            )
        }
        val shapeB = remember {
            RoundedPolygon.star(
                6,
                rounding = CornerRounding(0.1f)
            )
        }
        val morph = remember {
            Morph(shapeA, shapeB)
        }
        val interactionSource = remember {
            MutableInteractionSource()
        }
        val isPressed by interactionSource.collectIsPressedAsState()
        val animatedProgress = animateFloatAsState(
            targetValue = if (isPressed) 1f else 0f,
            label = "progress",
            animationSpec = spring(dampingRatio = 0.4f, stiffness = Spring.StiffnessMedium)
        )
        Text(text = "ClickToShape")
        Box(
            modifier = Modifier
                .size(200.dp)
                .padding(8.dp)
                .clip(MorphPolygonShape(morph, animatedProgress.value))
                .background(Color(0xFF80DEEA))
                .size(200.dp)
                .clickable(interactionSource = interactionSource, indication = null) {
                }
        ) {
            Text("Hello", modifier = Modifier.align(Alignment.Center))
        }
    }

    //为形状无限变形添加动画效果
    class CustomRotatingMorphShape(
        private val morph: Morph,
        private val percentage: Float,
        private val rotation: Float
    ) : Shape {

        private val matrix = Matrix()
        override fun createOutline(
            size: Size,
            layoutDirection: LayoutDirection,
            density: Density
        ): Outline {
            // Below assumes that you haven't changed the default radius of 1f, nor the centerX and centerY of 0f
            // By default this stretches the path to the size of the container, if you don't want stretching, use the same size.width for both x and y.
            matrix.scale(size.width / 2f, size.height / 2f)
            matrix.translate(1f, 1f)
            matrix.rotateZ(rotation)

            val path = morph.toPath(progress = percentage).asComposePath()
            path.transform(matrix)

            return Outline.Generic(path)
        }
    }

    @Composable
    private fun RotatingScallopedProfilePic() {
        val shapeA = remember {
            RoundedPolygon(
                12,
                rounding = CornerRounding(0.2f)
            )
        }
        val shapeB = remember {
            RoundedPolygon.star(
                12,
                rounding = CornerRounding(0.2f)
            )
        }
        val morph = remember {
            Morph(shapeA, shapeB)
        }
        val infiniteTransition = rememberInfiniteTransition("infinite outline movement")
        val animatedProgress = infiniteTransition.animateFloat(
            initialValue = 0f,
            targetValue = 1f,
            animationSpec = infiniteRepeatable(
                tween(2000, easing = LinearEasing),
                repeatMode = RepeatMode.Reverse
            ),
            label = "animatedMorphProgress"
        )
        val animatedRotation = infiniteTransition.animateFloat(
            initialValue = 0f,
            targetValue = 360f,
            animationSpec = infiniteRepeatable(
                tween(6000, easing = LinearEasing),
                repeatMode = RepeatMode.Reverse
            ),
            label = "animatedMorphProgress"
        )
        Box(
            modifier = Modifier.fillMaxSize(),
            contentAlignment = Alignment.Center
        ) {
            Image(
                painter = painterResource(id = R.drawable.tou_xiang),
                contentDescription = "Dog",
                contentScale = ContentScale.Crop,
                modifier = Modifier
                    .clip(
                        CustomRotatingMorphShape(
                            morph,
                            animatedProgress.value,
                            animatedRotation.value
                        )
                    )
                    .size(200.dp)
            )
        }
    }


    @Composable
    private fun HeartShape(modifier: Modifier = Modifier) {
        val rounding = remember {
            val roundingNormal = 0.6f
            val roundingNone = 0f
            listOf(
                CornerRounding(roundingNormal),
                CornerRounding(roundingNone),
                CornerRounding(roundingNormal),
                CornerRounding(roundingNormal),
                CornerRounding(roundingNone),
                CornerRounding(roundingNormal),
            )
        }

        fun Float.toRadians() = this * PI.toFloat() / 180f

        val PointZero = PointF(0f, 0f)
        //radialToCartesian 函数将顶点转换为笛卡尔坐标：

        val vertices = remember {
            val radius = 1f
            val radiusSides = 0.8f
            val innerRadius = .1f
            fun directionVectorPointF(angleRadians: Float) =
                PointF(cos(angleRadians), sin(angleRadians))

            fun radialToCartesian(
                radius: Float,
                angleRadians: Float,
                center: PointF = PointZero
            ) = directionVectorPointF(angleRadians) * radius + center
            floatArrayOf(
                radialToCartesian(radiusSides, 0f.toRadians()).x,
                radialToCartesian(radiusSides, 0f.toRadians()).y,
                radialToCartesian(radius, 90f.toRadians()).x,
                radialToCartesian(radius, 90f.toRadians()).y,
                radialToCartesian(radiusSides, 180f.toRadians()).x,
                radialToCartesian(radiusSides, 180f.toRadians()).y,
                radialToCartesian(radius, 250f.toRadians()).x,
                radialToCartesian(radius, 250f.toRadians()).y,
                radialToCartesian(innerRadius, 270f.toRadians()).x,
                radialToCartesian(innerRadius, 270f.toRadians()).y,
                radialToCartesian(radius, 290f.toRadians()).x,
                radialToCartesian(radius, 290f.toRadians()).y,
            )
        }
        val polygon = remember(vertices, rounding) {
            RoundedPolygon(
                vertices = vertices,
                perVertexRounding = rounding
            )
        }
        Box(
            modifier = Modifier
                .drawWithCache {
                    val roundedPolygonPath = polygon
                        .toPath()
                        .asComposePath()
                    onDrawBehind {
                        scale(size.width * 0.5f, size.width * 0.5f) {
                            translate(size.width * 0.5f, size.height * 0.5f) {
                                drawPath(roundedPolygonPath, color = Color(0xFFF15087))
                            }
                        }
                    }
                }
                .size(400.dp)
        )
    }
}